package org.datascooter.bundle.attribute;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;

import org.datascooter.utils.TypeUtils;
import org.datascooter.utils.policy.ParamClass;

/**
 * An abstract class - ancestor of all attributes of EntityBundle
 * 
 * @author nemo
 * 
 */
@SuppressWarnings({
	"rawtypes"
})
public abstract class AbstractAttribute {

	public static final String GET = "get";
	public static final String IS = "is";
	public static final String SET = "set";
	public String name;
	protected boolean primitive;
	protected Class<?> getClass;
	protected ParamClass getParamClass;
	protected ParamClass setParamClass;
	protected Class setClass;

	public abstract void explore(Class<?> clazz) throws SecurityException, NoSuchMethodException;

	public abstract <T> Object getValue(Object obj) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;

	public abstract void setValue(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException, ParseException;

	public abstract <T extends AbstractAttribute> T copy();

	public AbstractAttribute(String name) {
		this.name = name;
	}

	public String getActorName() {
		return name;
	}

	protected void setGetClass(Class<?> clazz) {
		this.getClass = clazz;
		primitive = TypeUtils.isPrimitive(clazz);
		getParamClass = TypeUtils.getParamClass(clazz);
	}

	protected void setSetClass(Class<?> clazz) {
		this.setClass = clazz;
		setParamClass = TypeUtils.getParamClass(clazz);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractAttribute other = (AbstractAttribute) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "attr=" + name;
	}
}
